﻿using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp4
{
    public class Comprehensive
    {
        /**
         * 延迟队列在新版中已经被弃用 https://www.rabbitmq.com/docs/lazy-queues
         * 
         * 当消息发送到延迟队列时，根据设置的延迟时间进行等待。
         * 等待时间过后，如果消息未被消费者消费，则会进入绑定的死信队列。
         * 如果消费者消费了消息，但消息处理失败，消息会被发送到绑定的重试队列，进行重试操作。
         * 如果在重试队列中仍然无法处理成功，消息最终会被发送到死信队列。
         */
        public static void Producer(string[] args)
        {
            var factory = new ConnectionFactory { HostName = "supplier.xl24h.cn", Port = 5672, UserName = "admin", Password = "das@123!", VirtualHost = "/" };
            using var connection = factory.CreateConnection();
            using (var channel = connection.CreateModel())
            {
                // 声明死信交换机和死信队列
                channel.ExchangeDeclare("dead_letter_exchange", ExchangeType.Direct, durable: true);
                channel.QueueDeclare("dead_letter_queue", durable: true, exclusive: false, autoDelete: false);
                channel.QueueBind("dead_letter_queue", "dead_letter_exchange", "dead_letter_routing_key");

                // 声明重试交换机和重试队列
                channel.ExchangeDeclare("retry_exchange", ExchangeType.Direct, durable: true);
                channel.QueueDeclare("retry_queue", durable: true, exclusive: false, autoDelete: false, arguments: new Dictionary<string, object>
                {
                    // 设置消息的过期时间，作为重试间隔
                    {"x-message-ttl", 5000}, // 5 seconds
                    // 设置死信交换机
                    {"x-dead-letter-exchange", "dead_letter_exchange"},
                    // 设置死信路由键
                    {"x-dead-letter-routing-key", "dead_letter_routing_key"}
                });
                channel.QueueBind("retry_queue", "retry_exchange", "retry_routing_key");

                // 声明延迟队列（带有 TTL）
                var arguments = new Dictionary<string, object>
                {
                    {"x-dead-letter-exchange", "retry_exchange"}, // 消息过期后发送到重试交换机
                    {"x-dead-letter-routing-key", "retry_routing_key"}, // 消息过期后的路由键
                    {"x-message-ttl", 10000} // 10 seconds TTL
                };
                channel.QueueDeclare("delay_queue", durable: true, exclusive: false, autoDelete: false, arguments: arguments);
                channel.QueueBind("delay_queue", "retry_exchange", "delay_routing_key");

                // 发送消息到延迟队列
                var messageBody = Encoding.UTF8.GetBytes(args.Length > 0 ? args[0] : "This is a xxx message.");
                channel.BasicPublish(exchange: "", routingKey: "delay_queue", basicProperties: null, body: messageBody);

                Console.WriteLine("Message sent to delay queue.");
            }
        }
        /**
         * 
         * 
         *                   dead_letter_queue <-> dead_letter_routing_key
         *                           ↑  
         *                   dead_letter_exchange <-> retry_queue <-> retry_routing_key
         *                                                 ↑
         *                    ↑----------------------------                             
         * producer -> retry_exchange -> delay_queue <-> delay_routing_key
         * 
         *                   
         * 
         * 
         * 
         * 
         */
    }
}
